package com.ruoyi.system.controller;

import java.util.Date;

import ch.qos.logback.core.util.TimeUtil;
import com.google.common.collect.Maps;

import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.CallBackException;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.system.coretools.pay.PayUtils;
import com.ruoyi.system.coretools.pay.PayUtilsV2;
import com.ruoyi.system.domain.TPayHistory;
import com.ruoyi.system.domain.TUserInfo;
import com.ruoyi.system.domain.TUserMoneyChange;
import com.ruoyi.system.domain.dto.TUserInfoDto;
import com.ruoyi.system.mapper.TPayHistoryMapper;
import com.ruoyi.system.mapper.TUserInfoMapper;
import com.ruoyi.system.mapper.TUserMoneyChangeMapper;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ITUserInfoService;
import com.ruoyi.system.service.ITUserMoneyChangeService;
import com.ruoyi.system.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/system/pay")
public class PayController extends BaseController {
    private static final Logger log = LoggerFactory.getLogger(PayController.class);
    @Autowired
    TPayHistoryMapper tPayHistoryMapper;
    @Autowired
    TUserInfoMapper tUserInfoMapper;
    @Autowired
    PayUtilsV2 payUtils;

    @Autowired
    ITUserInfoService userInfoService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private TUserMoneyChangeMapper tUserMoneyChangeMapper;

    @Autowired
    ITUserMoneyChangeService itUserMoneyChangeService;


    /**
     * 充值回调
     * {
     * "type": "payment",
     * "uuid": "62f88b36-a9d5-4fa6-aa26-e040c3dbf26d",
     * "order_id": "97a75bf8eda5cca41ba9d2e104840fcd",
     * "amount": "3.00000000",
     * "payment_amount": "3.00000000",
     * "payment_amount_usd": "0.23",
     * "merchant_amount": "2.94000000",
     * "commission": "0.06000000",
     * "is_final": true,
     * "status": "paid",
     * "from": "THgEWubVc8tPKXLJ4VZ5zbiiAK7AgqSeGH",
     * "wallet_address_uuid": null,
     * "network": "tron",
     * "currency": "TRX",
     * "payer_currency": "TRX",
     * "additional_data": null,
     * "convert": {
     * "to_currency": "USDT",
     * "commission": null,
     * "rate": "0.07700000",
     * "amount": "0.22638000"
     * },
     * "txid": "6f0d9c8374db57cac0d806251473de754f361c83a03cd805f74aa9da3193486b",
     * "sign": "a76c0d77f3e8e1a419b138af04ab600a"
     * }
     * }
     *
     * @param jsonParam
     * @return
     */
    @PostMapping("/chongZhicallback")
    public AjaxResult chongZhicallback(HttpServletRequest request, @RequestBody Map<String, Object> jsonParam) {
        log.info("收到支付回调请求:{}", jsonParam);
        ISysConfigService configService = SpringUtils.getBean(ISysConfigService.class);
        String CALLBACK_WILTE_IP = configService.selectConfigByKey("pay.config.callback_wilte_ip");
        String origin = IpUtils.getIpAddr(request);
        //91.227.144.54
        if (!CALLBACK_WILTE_IP.equals("no")) {
            if (!CALLBACK_WILTE_IP.equals(origin)) {
                throw new ServiceException("回调IP地址来源不合法");
            }
        }


        try {

            String orderId = (String) jsonParam.get("order_id");
            //String userId = (String) jsonParam.get("user_id");
            float amount = Float.parseFloat(jsonParam.get("amount").toString());
            String status = jsonParam.get("status").toString();

            updateChongZhiInfo(orderId, amount, status);


            log.info("支付回调请求处理成功:{}", jsonParam);
            return AjaxResult.success();
        } catch (Exception e) {
            e.printStackTrace();

            //一旦有任何错误,回调数据先放支付死信队列，防止数据丢失方便后续特殊异常处理
            List<Map> mapList = new ArrayList<>();
            mapList.add(jsonParam);
            //回调信息先入库,防止出现数据错误丢失的问题
            redisCache.setCacheList("chongZhicallback", mapList);

            //这个Exception在全局异常处理里面要吃掉，必须跑出去让发起回调放知晓。
            log.info("支付回调请求处理失败,排除异常，等待重新发起:{}", jsonParam);
            return AjaxResult.success();
            //throw new CallBackException();
        }

    }


    /**
     * 充值回调
     * <p>
     * {
     * "type": "payout",
     * "uuid": "2b852d86-3cf1-43fb-b1bb-36f0b7d12151",
     * "order_id": "129359",
     * "amount": "207.00000000",
     * "merchant_amount": "207.30000000",
     * "commission": "0.30000000",
     * "is_final": true,
     * "status": "paid",
     * "txid": "0xcf8",
     * "currency": "USDT",
     * "network": "bsc",
     * "payer_currency": "USDT",
     * "payer_amount": "207.00000000",
     * "sign": "eff3afba8600af59c98b74155934da2d"
     * }
     */
    @PostMapping("/tixianCallback")
    public AjaxResult tixianCallback(HttpServletRequest request, @RequestBody Map<String, Object> jsonParam) {
        log.info("收到提现回调请求:{}", jsonParam);
        ISysConfigService configService = SpringUtils.getBean(ISysConfigService.class);
        /*String CALLBACK_WILTE_IP = configService.selectConfigByKey("pay.config.pay.config.callback_wilte_ip");
        String origin = IpUtils.getIpAddr(request);
        //91.227.144.54
        if (!CALLBACK_WILTE_IP.equals("no")) {
            if (!CALLBACK_WILTE_IP.equals(origin)) {
                throw new ServiceException("回调IP地址来源不合法");
            }
        }*/

        try {

            String order_id = (String) jsonParam.get("order_id");
            //String userId = (String) jsonParam.get("user_id");
            float amount = Float.parseFloat(jsonParam.get("amount").toString());

            String status = jsonParam.get("status").toString();
            //往数据库里面搓,做业务
            updateTiXianInfo(order_id, amount, status);


            log.info("提现回调请求处理成功:{}", jsonParam);
            return AjaxResult.success();
        } catch (Exception e) {
            e.printStackTrace();

            //一旦有任何错误,回调数据先放支付死信队列，防止数据丢失方便后续特殊异常处理
            List<Map> mapList = new ArrayList<>();
            mapList.add(jsonParam);
            //回调信息先入库,防止出现数据错误丢失的问题
            redisCache.setCacheList("tixianCallback", mapList);

            //这个Exception在全局异常处理里面要吃掉，必须跑出去让发起回调放知晓。
            log.info("提现回调请求处理失败,排除异常，等待重新发起:{}", jsonParam);
            return AjaxResult.success();
            //throw new CallBackException();
        }

    }

    @Transactional
    public void updateChongZhiInfo(String orderId, float amount, String status) {


        /*-
                confirm_check
                -
                paid
                -
                paid_over
                -
                fail
                -
                wrong_amount
                -
                cancel
                -
                system_fail
                -
                refund_process
                -
                refund_fail
                -
                refund_paid*/


        //往数据库里面搓,做业务
        //入库支付回调状态
        //查询
        TPayHistory tPayHistoryQuery = new TPayHistory();
        tPayHistoryQuery.setOrderId(orderId);
        List<TPayHistory> tPayHistorys = tPayHistoryMapper.selectTPayHistoryList(tPayHistoryQuery);
        //更新状态
        TPayHistory tPayHistory = tPayHistorys.get(0);
        tPayHistory.setAmount(new BigDecimal(amount));//实际支付金额

        log.info("充值回调状态:{},{}", orderId, status);
        if (status.equals("process") || status.equals("check")) {
            tPayHistory.setOperationStatus(0);
        }

        if (status.equals("paid") || status.equals("paid_over")) {
            tPayHistory.setOperationStatus(1);

            chongzhiSucess(tPayHistory);//充值成功后续流程
        }
        if (status.equals("fail") || status.equals("cancel") || status.equals("system_fail") || status.equals("wrong_amount")) {
            tPayHistory.setOperationStatus(2);

            chongzhiFaill(tPayHistory);//充值失败后续流程
        }




    }

    private void chongzhiSucess(TPayHistory tPayHistory) {
        tPayHistoryMapper.updateTPayHistory(tPayHistory);


        //更新金额
        //查询
        TUserInfo tUserInfo = tUserInfoMapper.selectTUserInfoById(tPayHistory.gettUserId());
        //处理前金额
        BigDecimal beforeMoney = tUserInfo.getMoney();
        //更新金额
        tUserInfo.setMoney(beforeMoney.add(tPayHistory.getAmount()));
        tUserInfoMapper.updateById(tUserInfo);


        //金额变更表，方便统一查询
        TUserMoneyChange tUserMoneyChange = new TUserMoneyChange();
        tUserMoneyChange.setSourceUserId(tPayHistory.gettUserId());
        //tUserMoneyChange.setTeamLevel(0);
        //tUserMoneyChange.setId(0L);
        tUserMoneyChange.setUserId(tPayHistory.gettUserId());//系统
        tUserMoneyChange.setType(5);//5充值 3提现
        tUserMoneyChange.setAuditStatus(4);//处理成功
        tUserMoneyChange.setMoney(tPayHistory.getAmount());
        tUserMoneyChange.setBeforeMoney(beforeMoney);
        tUserMoneyChange.setTime(DateUtils.getDate());
        tUserMoneyChange.setSourceId(-1l);//-1为系统行为已被操作不用再次操作
        tUserMoneyChange.setReason("系统充值");
        tUserMoneyChange.setIsDelete(0);
        //tUserMoneyChange.setSearchValue("");//数据库不存在此字段
        tUserMoneyChange.setCreateBy("管理员");
        tUserMoneyChange.setCreateTime(new Date());
        tUserMoneyChange.setUpdateBy("管理员");
        tUserMoneyChange.setUpdateTime(new Date());
        tUserMoneyChange.setRemark("用户充值成功系统金额变更");
        //tUserMoneyChange.setParams(Maps.newHashMap());//数据库不存在此字段

        tUserMoneyChangeMapper.insertTUserMoneyChange(tUserMoneyChange);
        //itUserMoneyChangeService.insertTUserMoneyChange(tUserMoneyChange);
    }




    private void chongzhiFaill(TPayHistory tPayHistory) {
        tPayHistoryMapper.updateTPayHistory(tPayHistory);

    }



    @Transactional
    public void updateTiXianInfo(String orderId, float amount, String status) {
        log.info("提现回调状态:{},{}", orderId, status);
                /*
            process	在流程中支出
            check	付款正在验证
            paid	支出成功
            fail	支付失败
            cancel	支付取消
            system_fail	系统错误发生了*/

        //往数据库里面搓,做业务
        //入库支付回调状态
        //查询
        TPayHistory tPayHistoryQuery = new TPayHistory();
        tPayHistoryQuery.setOrderId(orderId);
        List<TPayHistory> tPayHistorys = tPayHistoryMapper.selectTPayHistoryList(tPayHistoryQuery);
        //更新状态
        TPayHistory tPayHistory = tPayHistorys.get(0);
        tPayHistory.setOperationStatus(1);


        if (status.equals("process") || status.equals("check")) {
            tPayHistory.setOperationStatus(0);
        }

        if (status.equals("paid")) {
            tPayHistory.setOperationStatus(1);
            //成功
            tixianSucesss(tPayHistory);
        }
        if (status.equals("fail") || status.equals("cancel") || status.equals("system_fail")) {
            tPayHistory.setOperationStatus(2);
            tixianfail(tPayHistory);
        }





    }

    private void tixianSucesss(TPayHistory tPayHistory) {
        //金额不以回执为准，以元素没扣手续费的金额的为准，只是实际到账扣掉手续费。
        //tPayHistory.setAmount(new BigDecimal(amount));
        tPayHistoryMapper.updateTPayHistory(tPayHistory);


        //更新金额
        //查询
        TUserInfo tUserInfo = tUserInfoMapper.selectTUserInfoById(tPayHistory.gettUserId());
        //处理前金额
        BigDecimal beforeMoney = tUserInfo.getMoney();
        //更新金额
        tUserInfo.setFreezMoney(tUserInfo.getFreezMoney().subtract(tPayHistory.getAmount()));//冻结金额减去还原
        tUserInfoMapper.updateById(tUserInfo);


        //金额变更表，方便统一查询
        TUserMoneyChange tUserMoneyChange = new TUserMoneyChange();
        tUserMoneyChange.setSourceUserId(tPayHistory.gettUserId());
        //tUserMoneyChange.setTeamLevel(0);
        //tUserMoneyChange.setId(0L);
        tUserMoneyChange.setUserId(tPayHistory.gettUserId());//系统
        tUserMoneyChange.setType(3);//5充值 3提现
        tUserMoneyChange.setAuditStatus(4);//处理成功
        tUserMoneyChange.setMoney(tPayHistory.getAmount());
        tUserMoneyChange.setBeforeMoney(beforeMoney);
        tUserMoneyChange.setTime(DateUtils.getDate());
        tUserMoneyChange.setSourceId(-1l);//-1为系统行为已被操作不用再次操作
        tUserMoneyChange.setReason("系统提现");
        tUserMoneyChange.setIsDelete(0);
        //tUserMoneyChange.setSearchValue("");//数据库不存在此字段
        tUserMoneyChange.setCreateBy("管理员");
        tUserMoneyChange.setCreateTime(new Date());
        tUserMoneyChange.setUpdateBy("管理员");
        tUserMoneyChange.setUpdateTime(new Date());
        tUserMoneyChange.setRemark("用户提现成功系统金额变更");
        //tUserMoneyChange.setParams(Maps.newHashMap());//数据库不存在此字段

        tUserMoneyChangeMapper.insertTUserMoneyChange(tUserMoneyChange);
        //itUserMoneyChangeService.insertTUserMoneyChange(tUserMoneyChange);
    }





    private void tixianfail(TPayHistory tPayHistory) {
        //金额不以回执为准，以元素没扣手续费的金额的为准，只是实际到账扣掉手续费。
        //tPayHistory.setAmount(new BigDecimal(amount));
        tPayHistoryMapper.updateTPayHistory(tPayHistory);


        //更新金额
        //查询
        TUserInfo tUserInfo = tUserInfoMapper.selectTUserInfoById(tPayHistory.gettUserId());
        //处理前金额
        BigDecimal beforeMoney = tUserInfo.getMoney();
        //原金额加上冻结金额
        tUserInfo.setMoney(beforeMoney.add(tPayHistory.getAmount()));
        //减去冻结金额
        tUserInfo.setFreezMoney(tUserInfo.getFreezMoney().subtract(tPayHistory.getAmount()));//冻结金额减去还原
        tUserInfoMapper.updateById(tUserInfo);



    }
}
